home *** CD-ROM | disk | FTP | other *** search
- /*
-
- This program reads/writes MS-DOS formatted disks,
- using the CPM bios routines. The data is converted to/from
- C (non-ascii) files. The code is written so that it can
- be compiled with Small-C, but uses K&R standard I/O
- whenever possible.
-
- Author: Bob Alverson
- 8717 Empire Ct.
- Cincinnati, OH 45231
- 513-729-1676
-
- 1.1 9 DEC 83 Add ability to read all four IBM formats
- 1.0 27 NOV 83 First working version.
-
- */
-
-
- #include <stdio.h>
-
- /* Define the disk bios calls */
-
- #define SELDSK 9 /* Select disk drive */
- #define SETTRK 10 /* Select track */
- #define SETSEC 11 /* Select sector */
- #define SETDMA 12 /* Set DMA address */
- #define RDSEC 13 /* Read sector */
- #define WRSEC 14 /* Write sector */
- #define SECTRAN 16 /* Translate sector # */
-
- #define CURDSK 25 /* bdos selected disk */
-
- /* disk parameters */
-
- #define ALLMAX 1024 /* maximum alloc table size */
- #define DIRMAX 7*512 /* maximum directory size */
-
- /* misc data */
-
- #define DATSIZ 0x4000 /* size of data buffer */
-
- /* global data */
-
- char spttbl[4] = {32, 32, 36, 36}; /* sectors per track (logical) */
- int spt;
-
- char alltbl[4] = {8, 4, 8, 4}; /* size of alloc table / 128 */
- int allsiz;
-
- char dirtbl[4] = {28, 16, 28, 16}; /* size of directory / 128 */
- int dirsiz;
-
- int blktbl[4] = {8, 4, 8, 4}; /* size of block / 128 */
- int blksiz;
- int blklen; /* block size in bytes */
-
- int secofs;
- char allmap[ALLMAX]; /* allocation map */
- char dirbuf[DIRMAX]; /* directory data */
- char datbuf[DATSIZ]; /* data transfer buffer */
- char *datptr;
- int cpmdsk; /* cpm default disk */
- char xfile[20]; /* filename to transfer */
- int drive; /* drive of MSDOS disk */
- int blk; /* MSDOS block number */
- int xtra, blks; /* file length */
- FILE *cfile; /* output file stream */
-
- main()
- {
- fputs("\nRead MS-DOS disks, Version 1.1\nDec 9, 1983\n", stdout);
- do {
- fputs("Drive of MSDOS disk: ",stdout);
- fgets(xfile, 20, stdin);
- drive = toupper(*xfile) - 'A';
- if (drive < 0 || drive >= 16) {
- fputs("\n\7Drive spec error!\n", stderr);
- drive = -1; /* flag bad drive */
- }
- } /* do */
- while (drive < 0);
-
- cpmdsk = bdos(CURDSK, 0);
-
- bios(SELDSK, drive, 0); /* select disk drive */
- dettype();
-
- readdsk(4, allsiz, allmap); /* read allocation map in */
- readdsk(allsiz*2+4, dirsiz, dirbuf); /* read dir into memory */
-
- bios(SELDSK, cpmdsk, 1);
-
- while (getnam()) {
- if (find()) {
- cfile = fopen(xfile, "w");
- bios(SELDSK, drive, 1);
- datptr = datbuf;
- do {
- readblk(blk, datptr);
- if (blks) { /* complete sector */
- --blks;
- datptr += blklen;
- }
- else { /* partial sector */
- datptr += xtra;
- xtra = 0;
- }
- if (datptr > datbuf+DATSIZ-blklen) {
- bios(SELDSK, cpmdsk, 1);
- fwrite(datbuf, 1, datptr-datbuf, cfile);
- bios(SELDSK, drive, 1);
- datptr = datbuf;
- } /* if */
- nxtblk();
- } /* do */
- while (blks || xtra);
- bios(SELDSK, cpmdsk, 1);
- fwrite(datbuf, 1, datptr-datbuf, cfile);
- fclose(cfile);
- } /* if */
- else fputs("\nFile not found\n",stdout);
- } /* while */
- } /* main */
-
-
- dettype() /* determine disk type */
- {
- char secbuf[128];
- int dsktyp;
-
- readsec(0, 5, secbuf);
- dsktyp = (~ *secbuf) & 3;
-
- spt = spttbl[dsktyp];
- allsiz = alltbl[dsktyp];
- dirsiz = dirtbl[dsktyp];
- blksiz = blktbl[dsktyp];
-
- blklen = blksiz*128;
- secofs = ((allsiz - blksiz) << 1) + dirsiz + 4;
- } /* dettype */
-
-
- getnam()
- {
- char *str, *ptr;
-
- fputs("\nEnter filename: ", stdout);
- str = fgets(xfile, 20, stdin);
- if (ptr=strchr(xfile, '\n')) *ptr = '\0';
- return str;
- }
-
-
- /* read MSDOS block */
-
- readblk(blkno, bufptr)
- int blkno;
- char *bufptr;
- {
- readdsk((blkno * blksiz) + secofs, blksiz, bufptr);
- }
-
-
- readdsk(dsksec, numsec, bufptr)
- int dsksec,
- numsec;
- char *bufptr;
- {
- do {
- readsec(dsksec/spt, (dsksec%spt)+1, bufptr);
- bufptr += 128;
- ++dsksec;
- } /* do */
- while (--numsec); /* do all sectors requested */
- } /* readdsk */
-
-
- readsec(trk, sec, buf)
- int trk, sec;
- char *buf;
- {
- int retcode;
-
- bios(SETTRK, trk, 0);
- bios(SETSEC, sec, 0);
- bios(SETDMA, buf, 0);
- do {
- if (retcode = bios(RDSEC, 0, 0)) {
- char ask[3];
- fputs("\nDisk read error\nIgnore or Retry? ", stdout);
- fgets(ask, 3, stdin);
- if (toupper(*ask) == 'I') retcode = 0;
- } /* if */
- } /* do */
- while (retcode);
- } /* readsec */
-
-
- /* find next block (cluster) in chain */
-
- nxtblk()
- {
- int nblk;
- int *blkptr;
-
- blkptr = allmap + ((blk*3) >> 1);
- nblk = *blkptr;
- if (blk & 1) nblk >>= 4;
- blk = nblk & 0x0fff;
- }
-
- /* find file name in directory buffer */
-
- find()
- {
- char name[12];
- char *dirptr;
- int *blkptr;
-
- fmtfn(xfile, name);
- dirptr = dirbuf;
- while (strncmp(dirptr, name, 11) && *dirptr) dirptr += 32;
- if (*dirptr) {
- blk = *(blkptr = dirptr+26);
- xtra = *(++blkptr);
- blks = (xtra/blklen) + *(++blkptr)*(512/blksiz);
- xtra %= blklen;
- return 1;
- }
- return 0; /* not found */
- }
-
- /* format filename for directory search */
-
- fmtfn(text, buf)
- char *text, *buf;
- {
- if (text[1] == ':') text += 2; /* skip over drive */
-
- fmtbit(&text, buf, 8);
- fmtbit(&text, buf+8, 3);
-
- buf[11] = 0;
- }
-
- fmtbit(tptr, dest, cnt)
- int *tptr; /* should be char **text */
- char *dest;
- int cnt;
- {
- char *text;
-
- text = *tptr;
- while (--cnt >= 0) {
- if (*text && *text != '.')
- *dest = toupper(*text++); /* no macro allowed */
- else
- *dest = ' ';
- ++dest;
- }
- while (*text && *text != '.') ++text;
- if (*text == '.') ++text; /* scan past . */
- *tptr = text;
- }